package org.manon.json.analyse;

import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;

import org.manon.json.meta.HasUniqueId;

/**
 * A node for the Tree.
 * 
 * @author <a href="mailto:jacques.militello@gmail.com">Jacques Militello</a>
 */
public final class TreeNode<T extends HasUniqueId<E>,E extends Comparable<E>> implements HasUniqueId<E> {

	private final T _object;
	
	private SortedSet<TreeNode<T,E>> _childs;
			
	TreeNode(T object, Tree<T,E> tree) {
		_object = object;		
		_childs = new TreeSet<TreeNode<T,E>>(tree.getComparator());
	}
	
	/**
	 * @return the object
	 */
	public T getObject() {
		return _object;
	}
	
	/**
	 * @see org.manon.json.meta.HasUniqueId#getId()
	 */
	public E getId() {
		return _object.getId();
	}

	public void add(TreeNode<T, E> node) {
		_childs.add(node);
	}
	
	public boolean contains(E[] path, int pathIndex) {
		if (path.length == pathIndex) {
			return true;
		}
		for (TreeNode<T,E> node : _childs) {
			if (path[pathIndex].equals(node.getId())) {
				return node.contains(path, pathIndex+1);
			}
		}
		return false;
	}
	
	public TreeNode<T, E> search(String[] path, int pathIndex) {
		if (path.length == pathIndex) {
			return this;
		}
		for (TreeNode<T,E> node : _childs) {
			if (path[pathIndex].equals(node.getId())) {
				return node.search(path, pathIndex+1);
			}
		}
		return null;		
	}
	
	/**
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	public int compareTo(E o) {
		return _object.getId().compareTo(o);
	}

	public Iterator<TreeNode<T, E>> iterator() {
		return _childs.iterator();
	}
	protected String printTree(int increment) {
		
		final String prefix;
		StringBuilder builder = new StringBuilder();
		builder.append("\n|");
		for (int i = 0; i < (increment); ++i) {
			builder.append("-");
		}
		prefix = builder.toString();
		
		builder = new StringBuilder();
		builder.append("|-").append("{").append(getId()).append("}\t").append(_object);
		for (TreeNode<T,E> node : _childs) {
			builder.append(prefix).append(node.printTree(increment+6));
		}
		return builder.toString();
	}

	public boolean isLeaf() {
		return _childs.size() == 0;
	}


	void values(List<T> values) {
		for (TreeNode<T,E> node : _childs) {
			values.add(node._object);
			node.values(values);
		}
	}
}
